<?php


include "objectsHandler.php";
include "dataHandlerClass.php";
include "elementHandlerClass.php";
include "structHandlerClass.php";
/**
 * This class handles the XML structure, and allows accessing and saving the information of the structure.
 */
class XMLHandler {

    //Declaration of objects of our project.
    var $XMLdata;

    var $arrayElement ;
    var $arrayData;
    var $arrayStruct;


    private $separadorRelacion;
    private $separadorIds;
    private $separadorArbol;
    private $nombreRaiz;

    /**
     *Main constructor of the class.
     * @param <array> $parametros It contains information of the set of characters to use.
     */
    public function  __construct($parametros) {

        $this->separadorRelacion=$parametros['rel_char'];
        $this->separadorIds=$parametros['id_char'];
        $this->separadorArbol=$parametros['tree_char'];
        $this->nombreRaiz=$parametros['root_name'];

        $arrayElement = array();
        $arrayData= array();
        $arrayStruct= array();
    }
    /**
     *This function will load all the nodes contained inside the XML structure.
     * @global <xml> $XMLdata Contains all the information of the XML
     * @param <string> $path Path where the XML is located.
     */
    public function loadXML($path) {

        global $XMLdata;

        if (file_exists($path)) {
            $XMLdata = simplexml_load_file($path);
            //print_r($XMLdata);
            echo "Cargado correcto <br>";
        }

        else {
            exit('Failed to open '.$path);
        }
    }

    /**
     *This function implements the node generation from a XML using recursion
     * @param <string> $parentPath Path of the parent node.
     * @param <node> $child Descendant node of the current node.
     * @return <type>
     */
    function generateNodesREC($parentPath,$child) {

        foreach($child->children() as $children) {

            //If the node is an element
            if ($this->string_begins_with($children->TYPE,"ELEMENT")) {

                //The node is added to the element array.
                $element = new ObjectElement($parentPath.$this->separadorArbol.$children->getName(),$children->TYPE,$children->ID);
                $this->arrayElement[]= $element;

                //The node is added to the structure array.
                $node = new ObjectStruct($children->getName(),$children->TYPE,$parentPath,"");
                $this->arrayStruct[]= $node;
            }

            //If the node is an internal node...
            else   if ($children->TYPE=="NODE") {

                //The node is added to the structure array.
                $node = new ObjectStruct($children->getName(),$children->TYPE,$parentPath,"");
                $this->arrayStruct[]= $node;

            }

            //Otherwise the node is a leaf
            else {

                //The node is added to the structure.
                $node = new ObjectStruct($children->getName(),$children->TYPE,$parentPath,"");
                $this->arrayStruct[]= $node;
                //The node is added to the data structure.
                $data = new ObjectData($parentPath.$this->separadorArbol.$children->getName(),$children->VALUE);
                $this->arrayData[]= $data;
            }

            //The function is called recursively for all the nodes.
            $this->generateNodesREC($parentPath.$this->separadorArbol.$children->getName(),$children->VALUE);
        }
        //end of recursion
        return;
    }
    /**
     * Sort an array using a function to compare elements.
     */
    function sortElements() {
        usort($this->arrayElement, array("XMLHandler", "cmpTypes"));
    }

    /**
     *Function that is used to compare two elements of an array of elements.
     * @param <element> $a First element to compare.
     * @param <element> $b Second element to compare
     * @return <integer> 1 if the element are already placed in order.
     */
    function cmpTypes($a, $b) {
        return strcmp ($a->getType() , $b->getType()) ;
    }

    /**
     *Check if a string begins with another string given as a parameter.
     * @param <string> $string String to check
     * @param <string> $search String to be found it
     * @return <boolean> It returns true if the string is found it, false otherwise.
     */
    function string_begins_with($string, $search) {
        return (strncmp($string, $search, strlen($search)) == 0);
    }

    function printArraysStruct() {

        foreach ($this->arrayStruct  as $element) {
            echo "VALUE: ".$element->getValue() . " tipo: ". $element->getType()." padre: ". $element->getParentName()."<br>";
        }
    }

    function printArraysElement() {

        foreach ($this->arrayElement  as $element) {
            echo "Value: ".$element->getValue() . " ID: ". $element->getID()." y tipo: ". $element->getType()."<br>";
        }
//        print count($this->arrayElement);
    }

    function printArraysData() {

        foreach ($this->arrayData  as $element) {
            echo "Path_Structure: ".$element->getPathStructure() . " y valor ". $element->getValue()."<br>";
        }
//        print count($this->arrayElement);
    }

    /**
     *Function that generate all the nodes contained on the XML file.
     * @global <xml> $XMLdata Object that contains the xml information.
     */
    function generateNodes() {

        global $XMLdata;
        $this->generateNodesREC("",$XMLdata->children());
    }
}
?>